using System;
using System.Drawing;
using System.IO;
using System.Net;
using Threading;

namespace ThreadManagerTesterApp
{
    public class ImageDownloader : ThreadedWorkerManager<DownloadImageState>
    {
        public ImageDownloader()
        {
            this.AllWorkItemsFinished += ImageDownloaderAllTasksFinished;
            this.WorkItemFinished += ImageDownloaderWorkerFinished;
            this.WorkItemStarted += ImageDownloaderWorkItemStarted;      
        }

        void ImageDownloaderWorkItemStarted(object sender, WorkItemEventArgs args)
        {
            var handler = this.ImageDownloadStarted;
            
            if (handler != null)
            {
                handler(this, args.WorkItem.State);
            }
        }

        public void FetchAllImages()
        {
            this.DoAllWork();
        }
        
        public WorkItem<DownloadImageState> AddImageUrl(Uri imageUrl)
        {
            return this.EnqueueWork(this.DownloadImage, new DownloadImageState {Url = imageUrl});
        }
        
        public void DownloadImage(DownloadImageState state)
        {
            if (state == null)
            {
                return;
            }

            var client = new WebClient();
            var data = client.DownloadData(state.Url);
            var ms = new MemoryStream(data);
            state.DownloadedImage = new Bitmap(ms);
        }

        void ImageDownloaderWorkerFinished(object sender, WorkItemEventArgs args)
        {
            if (args.WorkItem.State != null)
            {
                var state = args.WorkItem.State;
                
                if (args.WorkItem.ThereWereErrors)
                {
                    state.LastErrorMessage = args.WorkItem.LastException.Message;
                }
                if (args.WorkItem.IsCanceled)
                {
                    state.WasCanceled = true;
                }
                
                if (this.ImageDownloaded != null)
                {
                    this.ImageDownloaded(this, state);
                }
            }
        }

        void ImageDownloaderAllTasksFinished()
        {
            var handler = AllImagesDownloaded;
            if (handler != null)
            {
                handler(this);
            }
        }


        public event ItemFinishedHandler ImageDownloaded;
        public event ItemStartedHandler ImageDownloadStarted;
        public event AllItemsDownloadedHandler AllImagesDownloaded;
    }

    public delegate void AllItemsDownloadedHandler(object sender);

    public delegate void ItemFinishedHandler(object sender, DownloadImageState state);
    public delegate void ItemStartedHandler(object sender, DownloadImageState state);
}